package cn.wen.yaling.aop.annotation.visit;

import cn.wen.yaling.commons.constant.Constants;
import cn.wen.yaling.commons.entity.WebVisitEntity;
import cn.wen.yaling.commons.handler.AbstractRequestAwareRunnable;
import cn.wen.yaling.commons.service.RedisService;
import cn.wen.yaling.commons.utils.IPUtils;
import cn.wen.yaling.commons.utils.StringUtils;
import cn.wen.yaling.xo.dao.WebVisitDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 异步记录日志
 *
 * @author: 陌溪
 * @create: 2020-03-05-8:59
 */
@Slf4j
public class SysLogHandle extends AbstractRequestAwareRunnable {

    /**
     * 模块UID
     */
    Integer moduleId;
    /**
     * 其它数据
     */
    String otherData;
    /**
     * Redis工具类对象
     */
    @Autowired
    private RedisService redisService;
    /**
     * 用户UID
     */
    private Integer userId;
    /**
     * 用户行为
     */
    private String behavior;

    /**
     * ip地址
     */
    private String ip;

    /**
     * 操作系统
     */
    private String os;

    /**
     * 浏览器
     */
    private String browser;

    private WebVisitDao webVisitDao;

    /**
     * 构造函数
     *
     * @param userId
     * @param ip
     * @param os
     * @param browser
     * @param behavior
     * @param moduleId
     * @param otherData
     */
    public SysLogHandle(Integer userId, String ip, String os, String browser, String behavior,
                        Integer moduleId, String otherData, RedisService redisService, WebVisitDao webVisitDao) {
        this.userId = userId;
        this.ip = ip;
        this.os = os;
        this.browser = browser;
        this.behavior = behavior;
        this.moduleId = moduleId;
        this.otherData = otherData;
        this.redisService = redisService;
        this.webVisitDao = webVisitDao;
    }


    /**
     * 遇见语录：Request请求结束后，异步线程拿主进程里数据会出现空指针异常【因此不能在子线程里操作Request对象】
     * 这个问题不一定每一次都出现，可能100次中有4~5次出现空指针异常，也就是说当 异步线程执行比主线程快 是没问题的
     * 这里为了避免这种情况，将避免在异步线程中操作Request对象
     */
    @Override
    protected void onRun() {
        System.out.println("============" + Thread.currentThread().getName());
        WebVisitEntity webVisit = new WebVisitEntity();
        webVisit.setIp(ip);
        //从Redis中获取IP来源
        String jsonResult = (String) redisService.get("IP_SOURCE" + Constants.SYMBOL_COLON + ip);
        if (StringUtils.isEmpty(jsonResult)) {
            String addresses = IPUtils.getAddresses("ip" + "=" + ip, "UTF-8");
            if (StringUtils.isNotEmpty(addresses)) {
                webVisit.setIpSource(addresses);
                redisService.setEx("IP_SOURCE" + Constants.SYMBOL_COLON + ip, addresses, 24, TimeUnit.HOURS);
            }
        } else {
            webVisit.setIpSource(jsonResult);
        }
        webVisit.setOs(os);
        webVisit.setBrowser(browser);
        webVisit.setUserId(userId);
        webVisit.setBehavior(behavior);
        webVisit.setModuleId(moduleId);
        webVisit.setOtherData(otherData);
        webVisit.setCreateTime(new Date());
        webVisit.setUpdateTime(new Date());
        webVisit.setStatus(1);
        webVisitDao.insert(webVisit);
    }
}
